﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using X23.Application.RoleManagement;
using X23.Application.UserManagement;
using X23.Extensions.AttributeExtensions;
using X23.Util.DateTimeUtil;

namespace X23.Extensions.FilterExtensions
{

    public class AuthFilter : IAsyncActionFilter
    {
        private readonly IUserManagementService _userManagementService;
        private readonly IRoleManagementService _roleManagementService;

        public AuthFilter(IUserManagementService userManagementService, IRoleManagementService roleManagementService)
        {
            _userManagementService = userManagementService;
            _roleManagementService = roleManagementService;
        }

        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            #region before
            //Console.WriteLine("AuthFilter-before");
            var currentUserId = await RefreshToken(context);
            var isPermission = await IsPermission(context, currentUserId);
            if (!isPermission)
            {
                context.Result = new ForbidResult();
                return;
            }
            //return new ForbidResult();
            #endregion

            await next();

            #region after
            //Console.WriteLine("AuthFilter-after");
            #endregion
        }


        /// <summary>
        /// 判断用户是否有按钮权限
        /// </summary>
        /// <param name="context">ActionFilter上下文</param>
        /// <param name="userId">用户Id</param>
        /// <returns></returns>
        private async Task<bool> IsPermission(ActionExecutingContext context,int userId)
        {
            var isPermission = true;
            var actionDescriptor = (Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)context.ActionDescriptor;
            var x23AuthorizeAttribute = actionDescriptor.MethodInfo.GetCustomAttributes(typeof(X23AuthorizeAttribute), false).FirstOrDefault();
            if (x23AuthorizeAttribute != null)
            {
                var x23Attribute = x23AuthorizeAttribute as X23AuthorizeAttribute;
                var x23PermissionList = x23Attribute.PermissionList;
                var x23ControllerName = x23Attribute.ControllerName;
                var roleList = await _roleManagementService.GetUserPermissionWithCache(userId);
                isPermission = roleList.Where(x => x.ControllerName == x23ControllerName && x23PermissionList.Contains(x.ButtonCode)).Count() == x23PermissionList.Count;
            }
            return await Task.FromResult(isPermission);
        }

        /// <summary>
        /// 刷新Token
        /// </summary>
        /// <param name="context">ActionFilter上下文</param>
        /// <returns>用户Id</returns>
        private async Task<int> RefreshToken(ActionExecutingContext context)
        {
            int userId = 0;
            var httpContext = context.HttpContext;
            var jwtHandler = new JwtSecurityTokenHandler();
            var token = httpContext.Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
            if (!string.IsNullOrWhiteSpace(token) && jwtHandler.CanReadToken(token))
            {
                var jwtToken = jwtHandler.ReadJwtToken(token);
                var validTime = jwtToken.ValidTo;

                var nameIdentifier = httpContext.User.Claims.Where(x => x.Type == ClaimTypes.NameIdentifier).FirstOrDefault();
                if (nameIdentifier != null && int.TryParse(nameIdentifier.Value, out userId))
                {
                    if (validTime > DateTimeUtil.DateTimeChineseNow && validTime.AddSeconds(-30) < DateTimeUtil.DateTimeChineseNow)
                    {
                        var refreshToken = await _userManagementService.GetTokenByUserId(userId);
                        httpContext.Response.Headers.Add("RefreshToken", refreshToken.Token);
                        httpContext.Response.Headers.Add("TokenExpiresTime", refreshToken.ExpiresTimeStr);
                    }
                }
            }
            return userId;
        }

    }
    //public class AuthFilter : IActionFilter
    //{
    //    public void OnActionExecuted(ActionExecutedContext context)
    //    {
    //        Console.WriteLine("action执行之后");
    //    }

    //    public void OnActionExecuting(ActionExecutingContext context)
    //    {
    //        var httpContext = context.HttpContext;
    //        Console.WriteLine("action执行之前");
    //        var jwtHandler = new JwtSecurityTokenHandler();
    //        var token = httpContext.Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
    //        if (!string.IsNullOrWhiteSpace(token) && jwtHandler.CanReadToken(token))
    //        {
    //            var jwtToken = jwtHandler.ReadJwtToken(token);
    //            var validTime = jwtToken.ValidTo;
    //            if (validTime.AddMinutes(5) > DateTime.UtcNow)
    //            {
    //                int userId = 0;
    //                var refreshToken = "";
    //                var nameIdentifier = httpContext.User.Claims.Where(x => x.Type == ClaimTypes.NameIdentifier).FirstOrDefault();

    //                if (!(nameIdentifier == null || !int.TryParse(nameIdentifier.Value, out userId)))
    //                {
    //                    var _userManagementService = httpContext.RequestServices.GetRequiredService<IUserManagementService>();
    //                    var user= _userManagementService.GetByIdAsync(userId).Result;
    //                    refreshToken = _userManagementService.GetTokenByUserId(user.Id).Result.Token;
    //                }
    //                httpContext.Response.Headers.Add("RefreshToken", refreshToken);
    //            }
    //        }
    //    }
    //}
}
